import { useEventListener } from 'ahooks';
import { useState } from 'react';

import { unref } from '../utils/unref';
import { useRafFn } from './use-raf-fn';
import { useResizeObserver } from './use-resize-observer';

export interface UseElementBoundingResult extends Omit<DOMRect, 'toJSON'> {
  isReady: boolean;
}

export function useElementBounding(
  target: MaybeRef<HTMLElement | null | undefined>
): UseElementBoundingResult {
  const targetEl = unref(target);

  const [bounding, setBounding] = useState<UseElementBoundingResult>(() => ({
    height: 0,
    bottom: 0,
    left: 0,
    right: 0,
    top: 0,
    width: 0,
    x: 0,
    y: 0,
    isReady: false
  }));

  const update = useRafFn(() => {
    if (targetEl) {
      const bounding = targetEl.getBoundingClientRect() as unknown as UseElementBoundingResult;
      bounding.isReady = true;
      setBounding(bounding);
    }
  });

  useResizeObserver(update, targetEl);

  useEventListener('scroll', update, { passive: true });

  useEventListener('resize', update, { passive: true });

  return bounding;
}

export type UseElementBoundingReturn = ReturnType<typeof useElementBounding>;
